package cart

import (
	"context"
	"runtime"

	"mall/service/forum/api/internal/biz/promotion"
	"mall/service/forum/api/internal/svc"
	"mall/service/forum/api/internal/types"
	"mall/service/promotion/rpc/promotionclient"

	"github.com/shopspring/decimal"
)

type Modifier struct {
	ActivityId       int64 ///
	RuleId           int64 ///
	CouponTemplateId int64
	CouponId         int64           ///
	ActivityAmount   decimal.Decimal ///
	CouponAmount     decimal.Decimal ///
	Status           int             //
	Effect           uint32
	EffectType       uint32
	EffectValue      string
}

// Context Context
type Context struct {
	Req            *types.GetShoppingCartReq
	Resp           *types.CheckoutInfo
	Ctx            context.Context
	SvcCtx         *svc.ServiceContext
	UserId         uint64
	UserRank       string                          // 用户等级名称
	CheckedMap     map[uint64]struct{}             // 选中的购物车项目
	SkuScopeInfos  []*promotionclient.SkuScopeInfo // 优惠是否使用
	PricingInfos   []*promotion.PricingInfo        // 商品信息列表，按照售价从高到低排序
	GemRatio       decimal.Decimal
	AccountGems    decimal.Decimal
	SkuAmountMap   map[uint64]decimal.Decimal // skuID => 单价x数量
	MutexMap       map[uint32]map[uint64]int64
	SkusAmount     decimal.Decimal
	SkusNumber     int64
	SkusWeight     decimal.Decimal
	ActivityAmount decimal.Decimal
	CouponAmount   decimal.Decimal
	Freight        decimal.Decimal
	FinalFreight   decimal.Decimal
	FinalAmount    decimal.Decimal
	Modifiers      []*Modifier
}

// Handler 处理
type Handler interface {
	// 自身的业务
	Do(c *Context) error // 这里进行各种验证
	// 设置下一个对象
	SetNext(h Handler) Handler
	// 执行
	Run(c *Context) error
}

// Next 抽象出来的 可被合成复用的结构体
type Next struct { //
	// 下一个对象
	nextHandler Handler
}

// SetNext 实现好的 可被复用的SetNext方法
// 返回值是下一个对象 方便写成链式代码
// 例如 nullHandler.SetNext(argumentsHandler).SetNext(signHandler).SetNext(frequentHandler)
func (n *Next) SetNext(h Handler) Handler {
	n.nextHandler = h

	return h
}

// Run 执行
func (n *Next) Run(c *Context) (err error) {
	// 由于go无继承的概念 这里无法执行当前handler的Do
	// n.Do(c)
	if n.nextHandler != nil {
		// 合成复用下的变种
		// 执行下一个handler的Do
		if err = (n.nextHandler).Do(c); err != nil {
			return err
		}

		// 执行下一个handler的Run
		return (n.nextHandler).Run(c)
	}

	return
}

// NullHandler 空Handler
// 由于go无继承的概念 作为链式调用的第一个载体 设置实际的下一个对象
type NullHandler struct { //
	// 合成复用Next的`nextHandler`成员属性、`SetNext`成员方法、`Run`成员方法
	Next
}

// Do 空Handler的Do
func (h *NullHandler) Do(c *Context) (err error) {
	// 空Handler 这里什么也不做 只是载体 do nothing...
	return
}

// 获取正在运行的函数名
func runFuncName() string {
	pc := make([]uintptr, 1)
	runtime.Callers(2, pc)
	f := runtime.FuncForPC(pc[0])

	return f.Name()
}
